﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;

namespace YArchitech.Revit
{
	public static class RevitUtility
	{
		public static UIDocument CurrentUIDocument { get; set; }

		public static Document CurrentDocument
		{
			get
			{
				return RevitUtility.CurrentUIDocument.Document;
			}
		}

		public static IEnumerable<LinkedDocument> LinkedDocuments { get; set; }

		public static SelectedElement PickMEPCurve(this UIDocument uiDocument, string prompt)
		{
			SelectedElement result;
			try
			{
				SelectedElement selectedElement;
				for (;;)
				{
					selectedElement = uiDocument.PickElementsByPoint(prompt, 0.05);
					if (selectedElement != null)
					{
						break;
					}
					TaskDialog.Show("盈建科提示", "没有选择实体或者选择实体不合适，请重新选择!");
				}
				result = selectedElement;
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException)
			{
				result = null;
			}
			catch (Exception ex)
			{
				Log.Error(new string[]
				{
					"PickReference Error : " + ex.Message
				});
				result = null;
			}
			return result;
		}

		public static SelectedElement PickElementsByPoint<T>(this UIDocument uiDocument, string prompt, double searchLength = 0.05) where T : Element
		{
			SelectedElement result;
			try
			{
				Reference reference = uiDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.PointOnElement, prompt);
				if (reference == null)
				{
					result = null;
				}
				else
				{
					Element element = uiDocument.Document.GetElement(reference);
					XYZ globalPoint = reference.GlobalPoint;
					RevitLinkInstance revitLinkInstance = element as RevitLinkInstance;
					if (revitLinkInstance == null)
					{
						result = new SelectedElement
						{
							SelectedPoint = globalPoint,
							Element = ((element is T) ? element : uiDocument.Document.GetElements(globalPoint, searchLength).FirstOrNull<Element>())
						};
					}
					else
					{
						result = new LinkedDocument(revitLinkInstance).GetSelectedElement<T>(globalPoint, searchLength);
					}
				}
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException ex)
			{
				ex.ToString();
				result = null;
			}
			catch (Exception ex2)
			{
				throw ex2;
			}
			return result;
		}

		public static SelectedElement PickElementsByPoint(this UIDocument uiDocument, string prompt, double searchLength = 0.05)
		{
			SelectedElement result;
			try
			{
				Reference reference = uiDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.PointOnElement, prompt);
				if (reference == null)
				{
					result = null;
				}
				else
				{
					Element element = uiDocument.Document.GetElement(reference);
					XYZ globalPoint = reference.GlobalPoint;
					RevitLinkInstance revitLinkInstance = element as RevitLinkInstance;
					if (revitLinkInstance == null)
					{
						result = new SelectedElement
						{
							SelectedPoint = globalPoint,
							Element = element
						};
					}
					else
					{
						result = new LinkedDocument(revitLinkInstance).GetSelectedElement(globalPoint, searchLength);
					}
				}
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException ex)
			{
				ex.ToString();
				result = null;
			}
			catch (Exception ex2)
			{
				throw ex2;
			}
			return result;
		}

		public static SelectedElement PickLinkElement<T>(this UIDocument uiDocument, string prompt, double searchLength = 0.05) where T : Element
		{
			SelectedElement result;
			try
			{
				Reference reference = uiDocument.Selection.PickObject(5, prompt);
				if (reference == null)
				{
					result = null;
				}
				else
				{
					Element element = uiDocument.Document.GetElement(reference);
					XYZ globalPoint = reference.GlobalPoint;
					RevitLinkInstance revitLinkInstance = element as RevitLinkInstance;
					if (revitLinkInstance == null)
					{
						result = new SelectedElement
						{
							SelectedPoint = globalPoint,
							Element = ((element is T) ? element : uiDocument.Document.GetElements(globalPoint, searchLength).FirstOrNull<Element>())
						};
					}
					else
					{
						result = new LinkedDocument(revitLinkInstance).GetSelectedElement<T>(globalPoint, searchLength);
					}
				}
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException ex)
			{
				ex.ToString();
				result = null;
			}
			catch (Exception ex2)
			{
				throw ex2;
			}
			return result;
		}

		public static List<Element> PickLinkElements<T>(this UIDocument uiDocument, string prompt) where T : Element
		{
			List<Element> result;
			try
			{
				List<Element> list = new List<Element>();
				IList<Reference> list2 = uiDocument.Selection.PickObjects(5, prompt);
				if (list2 == null)
				{
					result = null;
				}
				else
				{
					foreach (Reference reference in list2)
					{
						Element elementById = (uiDocument.Document.GetElement(reference) as RevitLinkInstance).GetLinkDocument().GetElementById(reference.LinkedElementId);
						list.Add(elementById);
					}
					result = list;
				}
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException ex)
			{
				ex.ToString();
				result = null;
			}
			catch (Exception ex2)
			{
				throw ex2;
			}
			return result;
		}

		public static SelectedElement PickElementsByFace<T>(this UIDocument uiDocument, string prompt, ref Reference refer, ref Transform trans, double searchLength = 0.05) where T : Element
		{
			SelectedElement result;
			try
			{
				Reference reference = uiDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.PointOnElement, prompt);
				refer = reference;
				if (reference == null)
				{
					result = null;
				}
				else
				{
					Element element = uiDocument.Document.GetElement(reference);
					XYZ globalPoint = reference.GlobalPoint;
					RevitLinkInstance revitLinkInstance = element as RevitLinkInstance;
					if (revitLinkInstance != null)
					{
						trans = revitLinkInstance.GetTransform();
					}
					if (revitLinkInstance == null)
					{
						result = new SelectedElement
						{
							SelectedPoint = globalPoint,
							Element = ((element is T) ? element : uiDocument.Document.GetElements(globalPoint, searchLength).FirstOrNull<Element>())
						};
					}
					else
					{
						result = new LinkedDocument(revitLinkInstance).GetSelectedElement<T>(globalPoint, searchLength);
					}
				}
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException ex)
			{
				ex.ToString();
				result = null;
			}
			catch (Exception ex2)
			{
				throw ex2;
			}
			return result;
		}

		public static IEnumerable<LinkedDocument> GetLinkedDocuments(this UIDocument uiDocument)
		{
			return uiDocument.Document.GetLinkedDocuments();
		}

		public static IEnumerable<LinkedDocument> GetLinkedDocuments(this Document document)
		{
			IEnumerable<LinkedDocument> enumerable = Enumerable.Empty<LinkedDocument>();
			IEnumerable<RevitLinkInstance> source = from ins in document.GetElements<RevitLinkInstance>()
			where ins.GetLinkDocument() != null
			select ins;
			if (!source.Any<RevitLinkInstance>())
			{
				return enumerable;
			}
			IEnumerable<LinkedDocument> enumerable2 = from ins in source
			select new LinkedDocument(ins);
			enumerable = enumerable.Concat(enumerable2);
			List<LinkedDocument> linkedLnkDoc = new List<LinkedDocument>();
			enumerable2.ToList<LinkedDocument>().ForEach(delegate(LinkedDocument lnkDoc)
			{
				linkedLnkDoc.AddRange(lnkDoc.Document.GetLinkedDocuments());
			});
			return enumerable.Concat(linkedLnkDoc);
		}

		public static LinkedDocument GetLinkedDocument(this Document document, ElementId elementIdInLinkDocument)
		{
			IEnumerable<LinkedDocument> linkedDocuments = document.GetLinkedDocuments();
			if (!linkedDocuments.Any<LinkedDocument>())
			{
				return null;
			}
			return linkedDocuments.FirstOrDefault((LinkedDocument lnkDoc) => lnkDoc.Document.Contains(elementIdInLinkDocument));
		}

		public static Connector GetNearestConnector(this IEnumerable<Element> elements, XYZ point)
		{
			Log.Info(new string[]
			{
				"SearchSysem RevitUtility GetNearestConnector"
			});
			return elements.GetAllConnectors().GetNearestConnector(point);
		}

		public static IEnumerable<Connector> GetAllConnectors(this IEnumerable<Element> elements)
		{
			IEnumerable<Connector> result;
			try
			{
				if (elements == null || !elements.Any<Element>())
				{
					result = Enumerable.Empty<Connector>();
				}
				else
				{
					result = elements.SelectMany((Element elem) => elem.GetConnectors());
				}
			}
			catch
			{
				result = Enumerable.Empty<Connector>();
			}
			return result;
		}

		public static bool IsLessThan(this XYZ p1, XYZ p2)
		{
			return p1.X < p2.X && p1.Y < p2.Y && p1.Z < p2.Z;
		}

		public static bool IsBiggerThan(this XYZ p1, XYZ p2)
		{
			return p1.X > p2.X && p1.Y > p2.Y && p1.Z > p2.Z;
		}
	}
}
